package com.xb.cloud.gateway.filter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.xb.cloud.gateway.client.Context;

public class InboundFilter implements GatewayFilter {

	private List<? extends GatewayFilter> filters = new ArrayList<GatewayFilter>();

	public void setFilters(List<? extends GatewayFilter> filters) {
		Collections.sort(filters, new Comparator<GatewayFilter>() {
			@Override
			public int compare(GatewayFilter o1, GatewayFilter o2) {
				return o1.filterOrder() - o2.filterOrder();
			}
		});

		this.filters = new ArrayList<GatewayFilter>(filters);
	}

	@Override
	public void doFilter(Context xbContext, GatewFilterChain chain) {
		new VirtualFilterChain(chain, this.filters).doFilter(xbContext);
	}

	@Override
	public int filterOrder() {
		return 0;
	}

	@Override
	public void init() {
		for (GatewayFilter filter : this.filters) {
			filter.init();
		}
	}

	@Override
	public void destroy() {
		for (int i = this.filters.size(); i-- > 0;) {
			GatewayFilter filter = this.filters.get(i);
			filter.destroy();
		}
	}

	private static class VirtualFilterChain implements GatewFilterChain {

		private final List<? extends GatewayFilter> additionalFilters;

		private int currentPosition = 0;

		public VirtualFilterChain(GatewFilterChain chain, List<? extends GatewayFilter> additionalFilters) {
			this.additionalFilters = additionalFilters;
		}

		@Override
		public void doFilter(Context xbContext) {
			if (this.currentPosition < this.additionalFilters.size()) {
				this.currentPosition++;
				GatewayFilter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
				nextFilter.doFilter(xbContext, this);
			}
		}
	}
}
